package com.tamartech.greendb.reports;

import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;

import com.Ostermiller.util.CSVPrinter;
import com.tamartech.greendb.dao.AddressDAO;
import com.tamartech.greendb.dao.WardDAO;
import com.tamartech.greendb.dao.ElectionDAO;
import com.tamartech.greendb.dao.ElectoralRollDAO;
import com.tamartech.greendb.dao.ElectoralRollEntryDAO;
import com.tamartech.greendb.data.Ward;
import com.tamartech.greendb.data.Election;
import com.tamartech.greendb.data.ElectoralRoll;
import com.tamartech.greendb.data.ElectoralRollEntry;
import com.tamartech.greendb.data.Person;
import com.tamartech.greendb.data.VotingInfo;

public class VotingInfoCSVReport
{
    private static Logger log = Logger.getLogger (VotingInfoCSVReport.class);
    private static SimpleDateFormat formatDate = new SimpleDateFormat ("dd/MM/yyyy");

    public static void main(String[] args) throws Exception
    {
        File outFile = new File (args[0]);
        String constituencyName = args[1];
        Date rollDate = formatDate.parse(args[2]);
        
        ElectoralRollDAO erDAO = new ElectoralRollDAO();
        
        // see if there is already an ElectoralRoll object with the given date
        ElectoralRoll roll = erDAO.getByDate(rollDate);
        
        if (roll == null)
        {
            roll = new ElectoralRoll();
            roll.setDate(rollDate);
            erDAO.save(roll);
        }
        
        WardDAO constituencyDAO = new WardDAO();
        
        Ward constituency = constituencyDAO.get(constituencyName);

        ElectoralRollEntryDAO electoralRollEntryDAO = new ElectoralRollEntryDAO();

        List<ElectoralRollEntry> entries = electoralRollEntryDAO.listByRoll(roll);
        
        Collections.sort(entries, new Comparator<ElectoralRollEntry>()
                {

                    @Override
                    public int compare(ElectoralRollEntry l, ElectoralRollEntry r)
                    {
                        return l.getReference().compareTo(r.getReference());
                    }
            
                });

        ElectionDAO electionDAO = new ElectionDAO();
        
        Election e2007 = electionDAO.getByDate(formatDate.parse("01/05/2007"));
        Election e2008 = electionDAO.getByDate(formatDate.parse("01/05/2008"));
        
        AddressDAO addressDAO = new AddressDAO();
        
        CSVPrinter csv = new CSVPrinter (new FileOutputStream (outFile));
        
        ArrayList<String> headers = new ArrayList<String>();
                
        headers.add("Code 1");
        headers.add("Code 2");
        headers.add("Surname");
        headers.add("First Names");
        headers.add("Address1");
        headers.add("Address2");
        headers.add("Address3");
        headers.add("Postcode");
        headers.add("New This Year");
        headers.add("Vote Type");
        headers.add("Voting Info 2007");
        headers.add("Voting Info 2008");
        headers.add("Notes");
        
        csv.println((String[])headers.toArray(new String[0]));
                
        for (ElectoralRollEntry entry : entries)
        {
            if (constituency.equals(addressDAO.findAddressConstituency(entry.getAddress(), entry.getElectoralRoll())))
            {
                //log.info(entry.getRefPrefix() + entry.getRefSuffix());
                ArrayList<String> cols = new ArrayList<String>();
                
                cols.add(entry.getRefPrefix());
                cols.add(entry.getRefSuffix());
                cols.add(entry.getPerson().getSurname());
                cols.add(entry.getPerson().getFirstNames());
                cols.add(entry.getAddress().getAddress1());
                cols.add(entry.getAddress().getAddress2());
                cols.add(entry.getAddress().getAddress3());
                cols.add(entry.getAddress().getPostcode());
                //?? this is a bit rough and ready. If there is only one electoral roll with an entry for this person,
                // assume they are new. Should probably also check whether they have any associated PersonMatch objects
                cols.add(entry.getPerson().getElectoralRollEntries().size() == 1 ? "Yes" : "");
                cols.add(entry.getVoteType());
                cols.add(getVotingInfo (entry.getPerson(), e2007));
                cols.add(getVotingInfo (entry.getPerson(), e2008));
                cols.add("");
                
                csv.println((String[])cols.toArray(new String[0]));
            }
        }
        
        csv.close();
    }
    
    private static String getVotingInfo (Person p, Election e)
    {
        String str = "";
 
        for (VotingInfo vi : p.getVotingInfo())
        {
            if (e.compareTo(vi.getElection()) == 0)
            {
                str = nullToEmpty(vi.getVoted()) + "/" + nullToEmpty(vi.getParty()) + "/" + nullToEmpty(vi.getNotes());
            }
        }
        
        return str;
    }
    
    public static String nullToEmpty (String s)
    {
        return (s == null ? "" : s);
    }
}
